package UILayer;
import ControllerLayer.*;
import ModelLayer.*;
import java.util.ArrayList;

/**
 * Class responsible for the OrderUI.
 * 
 * @author Anders A.P., Anna K., Mie P., Danny P., Jakob K.
 * @version 1.0
 */
public class OrderUI {
    private OrderCtr orderCtr;
    private InputDialog inputDialog;

    /**
     * Constructor for objects of class OrderUI
     */
    public OrderUI() {
        orderCtr = new OrderCtr();
        inputDialog = new InputDialog();
    }

    /**
     * Method for creating the main Order menu.
     */
    public void startOrderUI() {
        boolean goOn = true;
        MenuList<Integer> m1 = new MenuList<Integer>("\fOrdre menu: ", "\nVælg: ");
        m1.addOption("1", "Opret ordre", 1);
        m1.addOption("2", "Opret tilbud", 2);
        m1.addOption("3", "Find tilbud", 3);
        m1.addOption("0", "Exit", 0);

        while(goOn) {
            Integer choice = m1.display();
            switch(choice) {
                case 0 : 
                goOn = false;
                break;

                case 1 :
                startOrder();
                break;

                case 2 : 
                startOffer();
                break;

                case 3 : 
                findOffer();
                break;
            }
        }
    }

    /**
     * Method for creating a new order.
     */
    private void startOrder() {
        startNewOrder();
        boolean goOn = true;
        MenuList<Integer> m1 = new MenuList<Integer>("\fOrdre: " + orderCtr.getOrder().getOrderNo() + "\nDato: " + orderCtr.getOrder().getOrderDate(), "\nVælg: ");
        m1.addOption("1", "Tilføj kunde", 1);
        m1.addOption("2", "Tilføj varer", 2);
        m1.addOption("3", "Afslut salg", 3);
        m1.addOption("0", "Exit", 0);

        while(goOn) {
            Integer choice = m1.display();
            switch(choice) {
                case 0 : 
                goOn = false;
                break;

                case 1 :
                if(orderCtr.getOrder().getCustomer() == null) {
                    addCustomer();
                }
                else {
                    System.out.println("Kunde er allerede tilføjet.");
                }
                break;

                case 2 :
                addItem();
                break;

                case 3 :

                if(orderCtr.getOrder().getOrderLines().size() > 0) {
                    goOn = false;
                    endOrder();
                }
                else {
                    System.out.println("Ingen varer er tilføjet!");
                    inputDialog.inputWait();
                }
                break;

                default : 
                System.out.println("Input ikke genkendt");   
                break;
            }
        }
    }

    /**
     * Method for creating a new offer, given to a certain customer.
     */
    private void startOffer() {
        startNewOrder();
        orderCtr.getOrder().setIsOffer(true);
        try {
            int i = inputDialog.inputInt("Tilføj kunde.\nIndtast kundenr.: ");
            orderCtr.addCustomer(i, false, false);
            System.out.println("Tilføj varer.");
            addItem();
            System.out.println("\nTilbud med ordrenr. " + orderCtr.getOrder().getOrderNo() + " er oprettet.");
            inputDialog.inputWait();
        }
        catch(Exception e) {
            System.out.println(e);
            inputDialog.inputWait();
        }
    }

    /**
     * Method for creating a order object.
     */
    private void startNewOrder() {
        orderCtr.startOrder();
    }

    /**
     * Method which initiates the UI for finding, and modifying offers, given to a certain customer.
     */
    private void findOffer() {
        boolean goOn = true;
        Order offer = null;
        try {
            int i = inputDialog.inputInt("Indtast kundenr: ");
            ArrayList<Order> offers = orderCtr.findOffer(i);
            if(offers.size() > 0) {
                MenuList<Integer> m1 = new MenuList<Integer>("\fTilbud på kunde nr: " + i, "\nVælg: ");
                for(int o = 1; o-1 < offers.size(); o++) {
                    m1.addOption(o+ "", "Tilbud: " + offers.get(o-1).getOrderNo(), o);
                }
                m1.addOption("0", "Exit", 0);

                while(goOn) {

                    Integer choice = m1.display();
                    if(choice > 0 && choice <= offers.size()) {
                        goOn = false;
                        offer = offers.get(choice-1);
                        decideOffer(offer);
                    }
                    else if(choice == 0) {
                        goOn = false;
                    }
                    else {
                        System.out.println("Input ikke genkendt");
                        inputDialog.inputWait();
                    }
                }
            }
        }
        catch(Exception e)
        {
            System.out.println("Kunden har ingen tilbud");
            inputDialog.inputWait();
        }
    }

    /**
     * Method for adding a customer to an order. If a customer is indeed found and added, it will ask weather packing and delivery is wanted.
     */
    private void addCustomer() {
        int o = inputDialog.inputInt("Indtast kundenr.: ");
        try {
            orderCtr.addCustomer(o, false, false);
            boolean packing = false;
            boolean delivery = false;

            packing = inputDialog.inputBoolean("Ønskes pakning ");

            if(packing == true) {
                delivery = inputDialog.inputBoolean("Ønskes levering ");
            }

            orderCtr.addCustomer(o, packing, delivery);
        }
        catch(Exception e) {
            System.out.println("Kunde ikke fundet"); 
            inputDialog.inputWait();
        }

    }

    /**
     * Method for creating a menu when an offer is transformed to an order.
     */
    private void finishOfferToOrder() {
        boolean goOn = true;
        orderCtr.offerToOrder();
        MenuList<Integer> m1 = new MenuList<Integer>("\fOrdre: " + orderCtr.getOrder().getOrderNo() + "\nDato: " + orderCtr.getOrder().getOrderDate(), "\nVælg: ");
        m1.addOption("1", "Pakning og levering", 1);
        m1.addOption("2", "Tilføj varer", 2);
        m1.addOption("3", "Afslut salg", 3);
        m1.addOption("0", "Exit", 0);

        while(goOn) {
            Integer choice = m1.display();
            switch(choice){
                case 0 : 
                goOn = false;
                break;

                case 1 :
                decidePacking();
                break;

                case 2 :
                addItem();
                break;

                case 3 :
                goOn = false;
                endOrder();
                break;

                default : 
                System.out.println("Input ikke genkendt");
                inputDialog.inputWait();
                break;
            }
        }
    }

    /**
     * Method for choosing packing and delivery for a order, prevoisly created as offer. 
     */
    private void decidePacking() {
        boolean packing = false;
        boolean delivery = false;

        packing = inputDialog.inputBoolean("Ønskes pakning? ");

        if(packing == true) {
            delivery = inputDialog.inputBoolean("Ønskes levering? ");
        }

        orderCtr.addCustomer(orderCtr.getOrder().getCustomer().getCustomerNo(), packing, delivery);
    }

    /**
     * Method for choosing weather to modify a offer, or to turn it into a order.
     */
    private void decideOffer(Order o) {
        boolean goOn = true;
        orderCtr.setOrder(o);
        listOrder();
        MenuList<Integer> m1 = new MenuList<Integer>("", "\nVælg: ");
        m1.addOption("1", "Rediger tilbud", 1);
        m1.addOption("2", "Tilbud til ordre", 2);
        m1.addOption("0", "Exit", 0);

        while(goOn) {
            Integer choice = m1.display();
            switch(choice) {
                case 1: 
                modifyOffer();
                break;

                case 2: 
                goOn = false;
                finishOfferToOrder();
                break;

                case 0:
                goOn = false;
                break;

                default:
                System.out.println("Input ikke genkendt");
                break;
            }
        }
    }

    /**
     * Method for modifying an offer.
     */
    private void modifyOffer() {
        ArrayList<OrderLine> orderLines = orderCtr.getOrder().getOrderLines();
        boolean modifying = true;
        while(modifying)
        {
            MenuList<Integer> m1 = listOrderLines(orderCtr.getOrder());
            Integer choice = m1.display();
            if(choice > 0 && choice <= orderLines.size())
            {
                modifyLine(orderLines.get(choice-1));
            }
            else if(choice == 0)
            {
                modifying = false;
            }
            else if(choice == orderLines.size()+1) {
                addItem();
            }
            else
            {
                System.out.println("Input ikke genkendt");
            }
            modifying = inputDialog.inputBoolean("\nFortsæt redigering af tilbud?");
        }
    }

    /**
     * Method for creating a menu with all the orderlines on the order + an option for adding new orderlines.
     */
    private MenuList<Integer> listOrderLines(Order o) {
        MenuList<Integer> m1 = new MenuList<Integer>("\fTilbud: " + orderCtr.getOrder().getOrderNo() + "\nDato: " + orderCtr.getOrder().getOrderDate(), "\nVælg: ");
        ArrayList<OrderLine> orderLines = o.getOrderLines();
        for(int i = 0; i < orderLines.size(); i++)
        {
            m1.addOption((i+1) + "","Rediger linje:    Varenr. " + orderLines.get(i).getItem().getID() + " Varenavn: " + orderLines.get(i).getItem().getName() + " Antal: " + orderLines.get(i).getQuantity(), i+1);
        }
        m1.addOption((orderLines.size()+1) + "", "Tilføj vare", orderLines.size()+1);
        m1.addOption("0", "Exit", 0);

        return m1;
    }

    /**
     * Method for modifying or deleting an orderLine. 
     */
    private void modifyLine(OrderLine ol) {
        boolean change = inputDialog.inputBoolean("Ændr antal?");
        if(change) {
            int i = inputDialog.inputInt("Nyt antal: ");
            ol.setQuantity(i);
        }
        else {
            boolean delete = inputDialog.inputBoolean("Slet vare?");
            if(delete) {
                orderCtr.getOrder().removeOrderLine(ol);
                System.out.println("\nVaren er slettet.");
                inputDialog.inputWait();
            }
        }
    }

    /**
     * Method for adding an item to an order. Will add items until prompted not to.
     */
    private void addItem() {
        ItemCtr itemCtr = new ItemCtr();
        boolean adding = true;
        while(adding) {
            int id = inputDialog.inputInt("Indtast varenr.: ");
            try {
                itemCtr.retrieveItem(id);
                boolean legit = false;
                int quantity = 0;
                while(!legit) {
                    quantity = inputDialog.inputInt("Indtast antal: ");
                    if(quantity <= 0) {
                        System.out.println("Input ikke acceptabelt!");
                    }
                    else {
                        legit = true;
                    }
                }
                orderCtr.addItem(id, quantity);
            }
            catch(Exception e) {
                System.out.println(e);
                inputDialog.inputWait();
            }
            adding = inputDialog.inputBoolean("Ønskes flere varer tilføjet?");                
        }   
    }

    /**
     * Method for ending an order. Will print the total price of the order, and prompt the user to pay the required amount. 
     */
    private void endOrder() {
        listOrder();
        if (orderCtr.getOrder().getCustomer() == null || (orderCtr.getOrder().getCustomer() !=null && inputDialog.inputBoolean("\nBetal kontant?"))){
            makePayment();
            inputDialog.inputWait();
        }
        else {
            System.out.println("\nFaktura udskrives");
            inputDialog.inputWait();
        }
        orderCtr.endOrder();
    }

    /**
     * Method for checking what change is due to the customer.
     */
    private void makePayment() {
        double amount = inputDialog.inputDouble("Betal: kr. " );
        try {
            System.out.println("Penge retur: kr. " + orderCtr.makePayment(amount));
        }
        catch(Exception e) {
            System.out.println("Det betalte beløb matchede ikke ordrens pris.");
        }
    }

    /**
     * Method for creating an invoice of a given order.
     */
    private void listOrder() {
        Order o = orderCtr.getOrder();
        ArrayList<OrderLine> orderLines = o.getOrderLines();
        if(o.getIsOffer() == true) {
            System.out.println("\fTilbud: " + orderCtr.getOrder().getOrderNo());
        }
        else {
            System.out.println("\fOrdre: " + orderCtr.getOrder().getOrderNo());
        }
        System.out.println("\nDato: " + orderCtr.getOrder().getOrderDate() +
            "\nSælger: " + orderCtr.getCurrentEmployee().getName() +
            "\nVarer:");
        for(OrderLine ol: orderLines) {
            System.out.println("Varenr.: " + ol.getItem().getID() + "\t" + ol.getItem().getName()+ "\t" + " Antal: " + ol.getQuantity()+ "\t" + " Linjepris: kr. " + ol.getLinePrice()); 
        }
        System.out.println("\nTotalpris: kr. " + o.getTotalPrice());
    }
}
